package math;

public class Vector3 {
    public float x;
    public float y;
    public float z;

    public Vector2 uv;

    public Vector3(float x, float y, float z){
        this.x = x;
        this.y = y;
        this.z = z;
    }

    public Vector3(){
        this.x = 0f;
        this.y = 0f;
        this.z = 0f;
    }

    public Vector3 clone(){
        return new Vector3(this.x, this.y, this.z);
    }

    public Vector3 addVectors( Vector3 a, Vector3 b ) {

        this.x = a.x + b.x;
        this.y = a.y + b.y;
        this.z = a.z + b.z;

        return this;

    }

    public Vector3 multiplyScalar( float scalar ) {

        this.x *= scalar;
        this.y *= scalar;
        this.z *= scalar;

        return this;

    }

    public Vector3 fromArray(float[] array){
        this.x = array[ 0 ];
        this.y = array[ 1 ];
        this.z = array[ 2 ];

        return this;
    }

    public Vector3 subVectors( Vector3 a, Vector3 b ) {

        this.x = a.x - b.x;
        this.y = a.y - b.y;
        this.z = a.z - b.z;

        return this;

    }

    public Vector3 normalize(){
        return this.divideScalar( this.length());
    }

    public float length(){
        return (float)Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
    }

    public Vector3 divideScalar( float scalar ) {

        if(scalar == 0){
            scalar = 1;
        }
        return this.multiplyScalar( 1 / scalar );

    }

    public float[] toArray(){
        float[] array = new float[3];
        array[ 0 ] = this.x;
        array[ 1 ] = this.y;
        array[ 2 ] = this.z;

        return array;
    }

    public Vector3 crossVectors( Vector3 a, Vector3 b ) {

        float ax = a.x, ay = a.y, az = a.z;
        float bx = b.x, by = b.y, bz = b.z;

        this.x = ay * bz - az * by;
        this.y = az * bx - ax * bz;
        this.z = ax * by - ay * bx;

        return this;

    }

    public float dot( Vector3 v ) {

        return this.x * v.x + this.y * v.y + this.z * v.z;

    }

    public Vector3 set( float x, float y, float z ) {

        this.x = x;
        this.y = y;
        this.z = z;

        return this;

    }

    public Vector3 applyQuaternion( Quaternion q ) {

        float x = this.x, y = this.y, z = this.z;
        float qx = q.x, qy = q.y, qz = q.z, qw = q.w;

        // calculate quat * vector

        float ix = qw * x + qy * z - qz * y;
        float iy = qw * y + qz * x - qx * z;
        float iz = qw * z + qx * y - qy * x;
        float iw = - qx * x - qy * y - qz * z;

        // calculate result * inverse quat

        this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy;
        this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz;
        this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx;

        return this;

    }

}
